﻿using GameFramework;
using GFTest;
using UnityEngine;

/// <summary>
/// 在鼠标点击或触摸发生时,触发一个通知
/// 该通知包含：鼠标/触摸、按钮/手指、当前点按的GameObject、所属NGUIForm
/// 孙希强 2017.03.20
/// </summary>
/// 
/// <remarks>
/// 1.代码从UICamera抄袭修改而来
/// 2.如果此脚本在“Script Execute Order”中配置比UICamera靠前,需要购选"executeBeforeUICamera"
/// 3.当"executeBeforeUICamera"构选时,会在触摸时调用一次Raycast，因为此时UICamera.lastHit还未更新
/// </remarks>
/// 
public class UITouchEvent : MonoBehaviour
{
    public UICamera bindCamera = null;
    public bool executeBeforeUICamera = true;
 
    private bool HandlesEvents { get { return UICamera.eventHandler == bindCamera; } }

    private UICamera.MouseOrTouch m_currentTouch = new UICamera.MouseOrTouch();
    private bool m_usingTouchEvents = true;
    private NGUIForm m_pressedForm = null;
    private GameObject m_pressedObject = null;

    private void Start()
    {
        if (bindCamera == null)
            bindCamera = gameObject.GetComponent<UICamera>();
    }
    
    void Update()
    {
        if (bindCamera == null)
            return;
        
        if (UICamera.ignoreAllEvents)
            return;
        
#if UNITY_EDITOR
        if (!Application.isPlaying || !HandlesEvents)
            return;
#else
        if (!HandlesEvents) 
            return;
#endif
        if (bindCamera.processEventsIn == UICamera.ProcessEventsIn.Update)
            ProcessEvents();
    }
    
    void LateUpdate()
    {
#if UNITY_EDITOR
        if (!Application.isPlaying || !HandlesEvents)
            return;
#else
		if (!HandlesEvents) 
            return;
#endif
        if (bindCamera.processEventsIn == UICamera.ProcessEventsIn.LateUpdate)
            ProcessEvents();
    }
    
    private void ProcessEvents()
    {
        if (bindCamera.useTouch)
            ProcessTouches();
        else if (bindCamera.useMouse)
            ProcessMouse();
    }
    
    private void ProcessMouse()
    {
        for (int i = 0; i < 3; ++i)
        {
            if (Input.GetMouseButtonDown(i))
            {
                if (executeBeforeUICamera)
                {
                    m_currentTouch.pos = Input.mousePosition;
                    UICamera.Raycast(m_currentTouch);
                    m_pressedObject = m_currentTouch.current;
                }
                else
                {
                    m_pressedObject = UICamera.lastHit.collider != null ? UICamera.lastHit.collider.gameObject : null;
                }

                m_pressedForm = m_pressedObject ? m_pressedObject.GetComponentInParent<NGUIForm>() : null;
                GameEntry.Event.Fire(this, ReferencePool.Acquire<UITouchEventArgs>().Fill(
                    true, true, i, m_pressedObject, m_pressedForm));
            }
            else if (Input.GetMouseButtonUp(i))
            {
                GameEntry.Event.Fire(this, ReferencePool.Acquire<UITouchEventArgs>().Fill(
                    false, true, i, m_pressedObject, m_pressedForm));
            }
        }
    }

    private void ProcessTouches()
    {
        int count = (UICamera.GetInputTouchCount == null) ? Input.touchCount : UICamera.GetInputTouchCount();
        for (int i = 0; i < count; ++i)
        {
            int fingerId;
            TouchPhase phase;

            if (UICamera.GetInputTouch == null)
            {
                UnityEngine.Touch touch = Input.GetTouch(i);
                phase = touch.phase;
                fingerId = touch.fingerId;
                m_currentTouch.pos = touch.position;
#if UNITY_WIIU && !UNITY_EDITOR
				// Unity bug: http://www.tasharen.com/forum/index.php?topic=5821.0
				currentTouch.pos.y = Screen.height - currentTouch.pos.position.y;
#endif
            }
            else
            {
                UICamera.Touch touch = UICamera.GetInputTouch(i);
                phase = touch.phase;
                fingerId = touch.fingerId;
                m_currentTouch.pos = touch.position;
            }
            
            if (phase == TouchPhase.Began)
            {
                if (executeBeforeUICamera)
                {
                    UICamera.Raycast(m_currentTouch);
                    m_pressedObject = m_currentTouch.current;
                }
                else
                {
                    m_pressedObject = UICamera.lastHit.collider != null ? UICamera.lastHit.collider.gameObject : null;
                }

                m_pressedForm = m_pressedObject ? m_pressedObject.GetComponentInParent<NGUIForm>() : null;
                GameEntry.Event.Fire(this, ReferencePool.Acquire<UITouchEventArgs>().Fill(
                    true, false, fingerId, m_pressedObject, m_pressedForm));
            }
            else if (phase == TouchPhase.Canceled || phase == TouchPhase.Ended)
            {
                GameEntry.Event.Fire(this, ReferencePool.Acquire<UITouchEventArgs>().Fill(
                    false, false, fingerId, m_pressedObject, m_pressedForm));
            }
        }

        if (count == 0)
        {
            if (m_usingTouchEvents)
            {
                m_usingTouchEvents = false;
                return;
            }

            if (bindCamera.useMouse)
                ProcessMouse();
        }
        else
        {
            m_usingTouchEvents = true;
        }
    }
}

